#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>  
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>

#define SIZE 256

char* argv[SIZE] = {NULL};
char command[SIZE];

void print_command_line();
void read_instruction(char command[SIZE]);
void execute_instruction();
 
int main()
{
    int quit = 0;

    while (!quit)
    {
        // 打印命令行
        print_command_line();

        // 读取指令
        read_instruction(command);

        // 执行指令
        execute_instruction();
    }


    return 0;
}

void print_command_line()
{
    // 获取用户名
    uid_t uid = getuid();
    struct passwd* pw = getpwuid(uid);
    char* user_name = pw->pw_name;
    // 获取主机名
    char hostname[SIZE] = {0};
    if (gethostname(hostname, SIZE) < 0)
    {
        perror("fail to print_command_line\n");
        exit(-1);
    }
    char* host_name = hostname;
    //host_name[SIZE - 1] = '\0'; // 确保字符串结尾

    // 获取路径
    char pathname[SIZE] = {0};
    char* path_name = getcwd(pathname, SIZE);
    //pathname[SIZE - 1] = '\0'; // 确保字符串结尾
    // 提示符
    char* prompt = ">";

    char command_line[SIZE];
    sprintf(command_line, "[%s@%s:%s]%s", user_name, host_name, path_name, prompt);

    printf("%s", command_line);
    fflush(stdout);
}

void read_instruction(char command[SIZE])
{

    if (fgets(command, SIZE, stdin) == NULL) 
    {
        //perror("fail to read_instruction\n");
        exit(errno);
    }
    
    int len = strlen(command);
    command[len - 1] = '\0';

    argv[0] = strtok(command, " ");

    int i = 1;
    while ((argv[i ++ ] = strtok(NULL, " ")) != NULL);

    argv[i] = NULL;
}

void execute_instruction()
{
    pid_t id = fork();

    if (id < 0)
    {
        exit(-1);
    }
    if (id == 0)
    {
        // child
        int i = 0;
        for (i; argv[i]; i ++ ) printf("%s", argv[i]);
        execvp(argv[0], argv);
        exit(errno);
    }
    else
    {
        // father
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if (rid < 0)
        {
            // ...
        }
    }
}